<template>
  <div class="menu-help">
    <a-card>
      <a-row>
        <a-col :span="12">
          <a-button type="primary" @click="linkArticleModal.visible = true">关联文章</a-button>
        </a-col>
        <!-- 搜索 -->
        <a-col :span="12">
          <a-row type="flex" justify="end">
            <a-select
              class="article-type"
              allow-clear
              v-model:value="articleType.type"
              placeholder="全部类型"
              @change="resetPage"
            >
              <a-select-option value="1">平台文章</a-select-option>
              <a-select-option value="2">外部链接</a-select-option>
            </a-select>
            <a-input-search
              v-model:value="articleType.title"
              style="width: 210px"
              placeholder="请填入文章标题"
              @search="resetPage"
            />
          </a-row>
        </a-col>
      </a-row>
      <div class="line"></div>
      <a-row type="flex">
        <a-col :span="3">
          <h3 class="menu-title">菜单路由</h3>
          <a-input-search
            v-model:value="menuName"
            style="margin-bottom: 8px"
            placeholder="Search"
          />
          <a-tree
            v-model:expandedKeys="expandedKeys"
            :autoExpandParent="autoExpandParent"
            :replaceFields="{ children: 'children', title: 'rightName', key: 'id' }"
            :tree-data="gData"
            @select="menuSearch"
          >
            <template #title="{ rightName }">
              <span v-if="rightName.indexOf(menuName) > -1">
                {{ rightName.substr(0, rightName.indexOf(menuName)) }}
                <span style="color: #f50">{{ menuName }}</span>
                {{ rightName.substr(rightName.indexOf(menuName) + menuName.length) }}
              </span>
              <span v-else>{{ rightName }}</span>
            </template>
          </a-tree>
        </a-col>
        <a-col :span="21" style="padding: 0 20px">
          <a-table
            :columns="columns"
            :data-source="state.dataSource"
            :pagination="false"
            :rowKey="record => `${record.columnId}-${record.id}`"
          >
            <!-- 浏览次数 -->
            <template #scanNum="{ record }">
              <span>
                <i class="iconfont icon-guankanshu-16px"></i>
                {{ record.scanNum || 0 }}
              </span>
            </template>

            <!-- 同意次数 -->
            <template #thumbsUp="{ record }">
              <span>
                <i class="iconfont icon-dianzan-16px"></i>
                {{ record.thumbsUp || 0 }}
              </span>
            </template>

            <!-- 反对次数 -->
            <template #thumbsDown="{ record }">
              <span>
                <i class="iconfont icon-fandui-32px"></i>
                {{ record.thumbsDown || 0 }}
              </span>
            </template>

            <template #sequence="{ record }">
              <a-input-number
                @change="changeSort($event, record)"
                @blur="confirmChangeSort"
                :value="record.sequence"
              ></a-input-number>
            </template>

            <!-- 操作 -->
            <template #handler="{ record }">
              <a @click="transfer(record)">转移</a>
              <span style="color: #1890ff; margin: 0 6px">|</span>
              <a @click="dissociated(record)">解除关联</a>
            </template>
          </a-table>
          <a-row style="margin-top: 20px" type="flex" justify="end">
            <a-pagination
              show-quick-jumper
              showSizeChanger
              v-model:pageSize="pagination.limit"
              v-model:current="pagination.page"
              :total="pagination.total"
              :showTotal="() => `共 ${pagination.total} 条数据`"
              @change="getList"
              @showSizeChange="getList"
            />
          </a-row>
        </a-col>
      </a-row>
      <!-- 转移弹框 -->
      <a-modal
        v-model:visible="showTransferModel.visible"
        :title="showTransferModel.title"
        @ok="confirmTransfer"
      >
        <a-tree
          show-icon
          v-model:expandedKeys="transferMenuKeys"
          :autoExpandParent="autoRmvExpandParent"
          class="menu-help_tree"
          @select="menuTreeSelect"
        >
          <a-tree-node v-for="item in gData" :key="item.id" :title="item.rightName">
            <template #icon>
              <div>
                <i class="iconfont icon-zonghoutai-wenzhang-16px"></i>
              </div>
            </template>
            <template v-if="item.children">
              <a-tree-node v-for="child in item.children" :key="child.id" :title="child.rightName">
                <template #icon>
                  <div>
                    <i class="iconfont icon-zonghoutai-wenzhang-16px"></i>
                  </div>
                </template>
              </a-tree-node>
            </template>
          </a-tree-node>
        </a-tree>
      </a-modal>
      <a-modal
        :width="800"
        :title="linkArticleModal.title"
        :visible="linkArticleModal.visible"
        @ok="confirmLinkArticle"
        @cancel="closeColArticle"
      >
        <h2 style="font-size: 16px">关联文章</h2>
        <list-transfer
          v-if="linkArticleModal.visible"
          :selectList="tags"
          select-placeholder="选择文章标签"
          :dataSource="articleList.dataSource"
          v-model:inputValue="searchArticleInfo.keywords"
          v-model:selectValue="searchArticleInfo.labelId"
          v-model:value="linkArticleKey.articleIds"
          @select="confirmGetTagList"
          @scroll="scollGetArticle"
        ></list-transfer>
        <h2 style="font-size: 16px; margin-top: 20px">关联栏目</h2>
        <tree-transfer
          v-if="linkArticleModal.visible"
          :t-data="gData"
          v-model:value="linkArticleKey.columnIds"
        />
      </a-modal>
    </a-card>
  </div>
</template>

<script>
import { reactive, defineComponent, ref, watch, toRaw } from 'vue';
import { findChildrenList } from '@/utils';
import { message } from 'ant-design-vue';
import {
  apiGetMenuHelpList,
  apiGetArticleTagList,
  apiGetArticleColList,
  apiAddRelationdArticle,
  apiGetArticleList,
  apiEditRelationdArticle,
  apiDissociated,
  apiEditArticleTransfer,
} from '@/api/articleManage';
import ListTransfer from '@/components/list-transfer';
import TreeTransfer from '@/components/tree-transfer';
import { concatIds, disposeTransferList } from '@/utils/helper';
const getParentKey = (key, tree) => {
  let parentKey;

  for (let i = 0; i < tree.length; i++) {
    const node = tree[i];

    if (node.children) {
      if (node.children.some(item => item.id === key)) {
        parentKey = node.id;
      } else if (getParentKey(key, node.children)) {
        parentKey = getParentKey(key, node.children);
      }
    }
  }

  return parentKey;
};

const columns = [
  {
    title: '关联文章',
    dataIndex: 'articleName',
    width: '30%',
  },
  {
    title: '栏目名称',
    dataIndex: 'columnName',
  },
  {
    title: '浏览次数',
    dataIndex: 'scanNum',
    slots: {
      customRender: 'scanNum',
    },
  },
  {
    title: '赞同数',
    dataIndex: 'thumbsUp',
    slots: {
      customRender: 'thumbsUp',
    },
  },
  {
    title: '反对数',
    dataIndex: 'thumbsDown',
    slots: {
      customRender: 'thumbsDown',
    },
  },
  {
    title: '排序',
    dataIndex: 'sequence',
    width: '8%',
    slots: {
      customRender: 'sequence',
    },
  },
  {
    title: '操作',
    dataIndex: 'handler',
    slots: {
      customRender: 'handler',
    },
  },
];

export default defineComponent({
  name: 'menuHelp',
  setup() {
    const articleType = reactive({
      type: undefined,
      title: '',
      columnId: '',
    });

    // 当前请求状态
    let isLoading = false;

    const menuList = ref([]);
    const gData = ref([]);
    const menuName = ref('');
    const expandedKeys = ref([]);
    const autoExpandParent = ref(true);

    /**
     * 获取菜单帮助栏目列表
     **/
    apiGetMenuHelpList().then(res => {
      menuList.value = disposeTransferList(res.list, 'rightName', 'id');
      gData.value = findChildrenList(menuList.value, 0);
    });

    // 监听搜索菜单名
    watch(expandedKeys, () => {
      autoExpandParent.value = false;
    });

    watch(menuName, value => {
      const expanded = menuList.value
        .map(item => {
          if (item.rightName.indexOf(value) > -1) {
            return getParentKey(item.id, gData.value);
          }
          return null;
        })
        .filter((item, i, self) => item && self.indexOf(item) === i);
      expandedKeys.value = expanded;
      menuName.value = value;
      autoExpandParent.value = true;
    });

    // 存放列表数据
    const state = reactive({ dataSource: [], loading: false });

    // 分页数据
    const pagination = reactive({ limit: 10, page: 1, total: 0 });

    /**
     * 获取列表
     **/
    const getList = async () => {
      if (state.loading) return;
      try {
        state.loading = true;
        const { page } = await apiGetArticleColList({
          page: pagination.page,
          limit: pagination.limit,
          articleType: articleType.type,
          keywords: articleType.title,
          type: 1,
          columnId: articleType.columnId[0],
        });
        pagination.total = page.total;
        state.dataSource = page.list;
      } finally {
        state.loading = false;
      }
    };
    getList();

    /**
     * 重置页码并获取数据
     **/
    const resetPage = () => {
      pagination.page = 1;
      getList();
    };

    /**
     * 选中菜单搜索
     **/
    const menuSearch = node => {
      articleType.columnId = node;
      getList();
    };

    const sequence = {};
    const changeSort = (e, row) => {
      sequence.number = e;
      sequence.info = toRaw(row);
    };

    /**
     * 更新排序
     **/
    const confirmChangeSort = () => {
      if (!sequence.number) return;
      apiEditRelationdArticle({
        sequence: sequence.number,
        articleId: sequence.info.id,
        columnId: sequence.info.columnId,
        type: 1,
      }).then(() => {
        getList();
        sequence.number = '';
        sequence.info = {};
      });
    };

    /**
     * 转移信息
     **/
    const removeForm = ref({});
    const transfer = form => {
      showTransferModel.visible = true;
      removeForm.value = form;
      transferMenuKeys.value = [form.columnId];
    };

    /**
     * 解除关联
     **/
    const dissociated = form => {
      const { columnId, id } = form;
      apiDissociated({ type: 1, columnId, articleId: id }).then(() => {
        getList();
        message.success('解除成功');
      });
    };

    // 展示转移弹框
    const showTransferModel = reactive({ visible: false, title: '转移' });
    const transferMenuKeys = ref([]);
    const autoRmvExpandParent = ref(false);
    const menuTreeSelect = node => {
      transferMenuKeys.value = node;
    };

    watch(transferMenuKeys, () => {
      autoRmvExpandParent.value = true;
    });

    /**
     * 转移请求
     **/
    const confirmTransfer = () => {
      if (removeForm.value.columnId === removeForm.value.id) return;
      apiEditArticleTransfer({
        columnId: removeForm.value.columnId,
        newColumnId: transferMenuKeys.value[0],
        articleId: removeForm.value.id,
        type: 1,
      }).then(() => {
        showTransferModel.visible = false;
        transferMenuKeys.value = [];
        getList();
      });
    };

    /**
     * 获取所有文章列表
     **/
    const articleList = reactive({
      page: 1,
      limit: 10,
      isAll: false,
      loading: false,
      dataSource: [],
    });

    /**
     * 将已经选中的选项筛选出
     **/
    const disposeSelectList = (list, selectValue) => {
      const selectList = [];
      list.forEach(item => {
        const selectItem = selectValue.find(value => item.id === +value);
        if (selectItem) {
          selectList.push(item);
        }
      });
      return selectList;
    };

    /**
     * 过滤已经选中的元素，避免重复添加
     **/
    const filterSelect = (list, selectIds) =>
      list.filter(item => !selectIds.some(articleId => +articleId === item.id));

    /**
     * 获取文章列表
     **/
    const searchArticleInfo = reactive({ keywords: '', labelId: undefined });
    const confirmGetArticle = async () => {
      try {
        articleList.loading = true;
        const { page } = await apiGetArticleList({
          page: articleList.page,
          limit: articleList.limit,
          labelId: searchArticleInfo.labelId,
          keywords: searchArticleInfo.keywords,
        });
        // 保存已选中的列表元素，即使重新调用接口，但是已选中的列表元素不可删除，否则会出现选中后更新搜索条件，已选中的选项被清空
        const selectList = disposeSelectList(articleList.dataSource, linkArticleKey.articleIds);
        // 过滤选中列表中的元素，否则可能存在左右两边均有出现的可能
        const list = filterSelect(page.list, linkArticleKey.articleIds);
        articleList.dataSource = disposeTransferList([...selectList, ...list], 'articleName', 'id');
      } finally {
        articleList.loading = false;
      }
    };
    confirmGetArticle();

    /**
     * 滚动事件
     **/
    const scollGetArticle = args => {
      const clientHeight = args[1].target.clientHeight;
      const scrollTop = args[1].target.scrollTop;
      const scrollHeight = args[1].target.scrollHeight;
      if (clientHeight + scrollTop === scrollHeight && !articleList.isAll) {
        articleList.page++;
        confirmScroll();
      }
    };

    /**
     * 滚动获取数据
     **/
    const confirmScroll = async () => {
      try {
        articleList.loading = true;
        const { page } = await apiGetArticleList({
          page: articleList.page,
          limit: articleList.limit,
          labelId: searchArticleInfo.labelId,
          keywords: searchArticleInfo.keywords,
        });
        const list = filterSelect(page.list, linkArticleKey.articleIds);
        articleList.dataSource = disposeTransferList(
          [...articleList.dataSource, ...list],
          'articleName',
          'id',
        );
        if (page.list.length < articleList.limit) {
          articleList.isAll = true;
        }
      } finally {
        articleList.loading = false;
      }
    };

    watch(searchArticleInfo, () => {
      articleList.page = 1;
      articleList.isAll = false;
      confirmGetArticle();
    });

    /**
     * 获取标签列表
     **/
    const tags = ref([]);
    const confirmGetTagList = (keywords = '') => {
      apiGetArticleTagList({ keywords }).then(res => {
        tags.value = res.list;
      });
    };

    /**
     * 关闭关联文章弹框
     **/
    const linkArticleModal = reactive({ visible: false, title: '关联文章' });
    const closeColArticle = () => {
      linkArticleModal.visible = false;
      linkArticleKey.articleIds = [];
      linkArticleKey.columnIds = [];
    };

    // 文章id和栏目id
    const linkArticleKey = reactive({ articleIds: [], columnIds: [] });

    /**
     * 关联文章
     **/
    const confirmLinkArticle = async () => {
      const articleIds = concatIds(linkArticleKey.articleIds);
      const columnIds = concatIds(linkArticleKey.columnIds);

      if (!columnIds || !articleIds) {
        return message.error('文章或栏目不能为空');
      }

      try {
        if (isLoading) return;
        isLoading = true;
        await apiAddRelationdArticle({ articleIds, columnIds, type: 1 });
        closeColArticle();
        getList();
        message.success('关联成功');
      } finally {
        isLoading = false;
      }
    };

    return {
      articleType,
      linkArticleKey,
      menuName,
      resetPage,
      expandedKeys,
      gData,
      autoExpandParent,
      menuSearch,
      columns,
      changeSort,
      confirmChangeSort,
      transfer,
      dissociated,
      confirmTransfer,
      autoRmvExpandParent,
      showTransferModel,
      transferMenuKeys,
      menuTreeSelect,
      confirmGetArticle,
      tags,
      getList,
      confirmGetTagList,
      articleList,
      searchArticleInfo,
      confirmLinkArticle,
      closeColArticle,
      linkArticleModal,
      state,
      pagination,
      scollGetArticle,
    };
  },
  components: {
    ListTransfer,
    TreeTransfer,
  },
});
</script>
<style lang="less">
.menu-help {
  .article-type {
    width: 150px;
    margin-right: 10px;
  }
  .line {
    margin: 10px 0;
    border-top: 1px dashed #eee;
  }
  .menu-title {
    font-weight: 700;
    font-size: 14px;
  }
}
.drawer {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
}
.menu-help_tree {
  .anticon {
    color: #c4c4c4;
  }
  .ant-tree-switcher_close {
    transform: scale(0.83333333) rotate(-90deg) !important;
  }
}
.icon-zonghoutai-wenzhang-16px {
  color: #1890ff;
}
</style>
